package composantes;

import java.awt.Color;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Vector;

import interfaces.Grille;

public class PlaqueCellulaire implements Grille{
	private Cellule[][] 		_cellule;
	private int 				_hauteur,
								_largeur,
								_generation;
	
	
	private int nb = 0;
	
	/*====================PlaqueCellulaire=======================*/
	private void init(int largeur, int hauteur){
		_hauteur = hauteur;
		_largeur = largeur;
		_generation = 0;
		
		_cellule = new Cellule[_hauteur][_largeur];
		for(int i = 0; i < _hauteur; i++){
			for(int j = 0; j < _largeur; j++){
				_cellule[i][j] = new Cellule(i, j);
			}
		}
	}
	
	public PlaqueCellulaire(){
		init(10, 10);
	}
	
	public PlaqueCellulaire(int hauteur, int largeur){
		init(hauteur, largeur);
	}
	
	public void setCellule(int x, int y, int etat, int type){
		_cellule[x][y].init(etat, type);
	}
	
	public ArrayList<Integer> verifier(){
		ArrayList<Integer> v = new ArrayList<Integer>();
		try{
			for(int i = 0; i < _hauteur; i++){
				for(int j = 0; j < _largeur; j++){
					switch(_cellule[i][j].getEtat()){
					case 1:
						if(nbVoisin(i, j, 2) == 2){
							_cellule[i][j].setProchainEtat(2);
							v.add(_cellule[i][j].getType());
						}
						break;
					case 2:
						if(nbVoisin(i, j, 2) > 2)
							_cellule[i][j].setProchainEtat(0);
						break;
					}
				}
			}
		}catch(Exception e){
			System.out.println(e.getMessage());
		}
		
		return v;
	}
	
	public int nbVoisin(int x, int y, int etat) throws ArrayIndexOutOfBoundsException{
		if(x < 0 || x >= _hauteur ||
		   y < 0 || y >= _largeur)
			throw new ArrayIndexOutOfBoundsException();
		
		int nbVoisin = 0;
		
		if(x != 0)
			if(_cellule[x-1][y].getEtat() == etat)
				nbVoisin++;
		
		if(x != _hauteur - 1)
			if(_cellule[x+1][y].getEtat() == etat)
				nbVoisin++;
		
		if (y != 0)
			if(_cellule[x][y-1].getEtat() == etat)
				nbVoisin++;
		
		if(y != _largeur - 1)
			if(_cellule[x][y+1].getEtat() == etat)
				nbVoisin++;
		return nbVoisin;
	}
	
	public void vieillir(){
		for(int i = 0; i < _hauteur; i++)
			for(int j = 0; j < _largeur; j++)
				_cellule[i][j].vieillir();
	}
	
	public Collection<Cellule> voisins(int x, int y){
		Collection<Cellule> c = new Vector<Cellule>();
		
		if(x < 0 || x >= _hauteur ||
		   y < 0 || y >= _largeur)
			throw new ArrayIndexOutOfBoundsException();
				
		if(x != 0)
			c.add(_cellule[x-1][y]);
		
		if(x != _hauteur - 1)
			c.add(_cellule[x+1][y]);
		
		if (y != 0)
			c.add(_cellule[x][y-1]);
		
		if(y != _largeur - 1)
			c.add(_cellule[x][y+1]);
		
		return c;
	}
	
	
	public Collection<Cellule> voisins(Cellule c) throws Exception{
		Collection<Cellule> v = new Vector<Cellule>();
		int x = -1,
			y = -1;
		
		for(int i = 0; i < _hauteur; i++)
			for(int j = 0; j < _largeur; j++)
				if(c == _cellule[i][j]){
					x = i;
					y = j;
					System.out.println("Cellule trouvée! " + i + " " + j);
					break;
				}
		
		if(x == -1)
			throw new Exception("Exception de cellule introuvable");
		
		if(x < 0 || x >= _hauteur ||
		   y < 0 || y >= _largeur)
			throw new ArrayIndexOutOfBoundsException();
				
		if(x != 0)
			if(_cellule[x-1][y].getEtat() < 2)
				v.add(_cellule[x-1][y]);
		
		if(x != _hauteur - 1)
			if(_cellule[x+1][y].getEtat() < 2)
				v.add(_cellule[x+1][y]);
		
		if (y != 0)
			if(_cellule[x][y-1].getEtat() < 2)
				v.add(_cellule[x][y-1]);
		
		if(y != _largeur - 1)
			if(_cellule[x][y+1].getEtat() < 2)	
				v.add(_cellule[x][y+1]);
		
		return v;
	}
	
	public int gagnant(){
		int typeGagnant = -1;
		for(int i = 0; i < _hauteur; i++)
			for(int j = 0; j < _largeur; j++)
				if(_cellule[i][j].getEtat() != 0)
					if(typeGagnant == -1)
						typeGagnant = _cellule[i][j].getType();
					else
						if(_cellule[i][j].getType() != typeGagnant)
							return -1;
		return typeGagnant;
	}
	
	/*=================================Grille=====================================*/
	@Override
	public int getLargeur() {
		return _largeur;
	}
	
	@Override
	public int getHauteur() {
		return _hauteur;
	}
	
	@Override
	public Object getElement(int x, int y) {
		return _cellule[x][y];
	}
	
	@Override
	public Color getColor(int x, int y) {
		Color c;
		switch(_cellule[x][y].getType()){
		case 0:
			c = new Color(128, 0, 0);
			break;
		case 1:
			c = new Color(0, 128, 0);
			break;
		case 2:
			c = new Color(0, 0, 128);
			break;
		default:
			c = new Color(128, 128, 0);
		}
		switch(_cellule[x][y].getEtat()){
		case 0:
			return Color.lightGray;
		case 1:
			return c.brighter();
		case 2:
			return c;
		default:
			return null;
		}
	}
	
	@Override
	public String getText(int x, int y) {
		return Integer.toString(_cellule[x][y].getEtat());
	}
	
	@Override
	public boolean canUpdate() {
		return true;
	}
	
	@Override
	public void update() {
		_generation++;
		vieillir();
		verifier();
	}
	
	@Override
	public void clear() {
		try{
			for(int i = 0; i < _hauteur; i++)
				for(int j = 0; j < _largeur; j++)
					_cellule[i][j].setPosition(i, j);
		}catch(Exception e){
			System.out.println(e.getMessage());
		}
	}

	@Override
	public void caseSelectionnee(int x, int y) {

	}
}